package Thread;

import java.util.Random;
import java.util.concurrent.*;

/**
 * @author 杜伟毅
 * @version 1.0
 * @since 2024/08/25
 * 线程同步--循环栅栏
 */
public class CyclicBarrierTest {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(5);
        // 计算总账的主线程
        Runnable main = () -> System.out.println("计算总账！");
        /**
         * 解释：等待3个线程运行完后，执行上面的main
         */
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3,main);

        Runnable task1 = () -> {
            ThreadUtils.sleep(new Random().nextInt(5000));
            System.out.println("计算山西分公司的账目");
            /**
             * 每一个线程执行完，则这段代码会减去1
             */
            try {
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (BrokenBarrierException e) {
                throw new RuntimeException(e);
            }
        };
        Runnable task2 = () -> {
            ThreadUtils.sleep(new Random().nextInt(5000));
            System.out.println("计算北京分公司的账目");
            try {
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (BrokenBarrierException e) {
                throw new RuntimeException(e);
            }
        };
        Runnable task3 = () -> {
            ThreadUtils.sleep(new Random().nextInt(5000));
            System.out.println("计算上海分公司的账目");
            try {
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (BrokenBarrierException e) {
                throw new RuntimeException(e);
            }
        };
        pool.submit(task1);
        pool.submit(task2);
        pool.submit(task3);

        /**
         * 重置，可以重复使用，CountDownLatch只能使用一次
         */
        cyclicBarrier.reset();
        pool.submit(task1);
        pool.submit(task2);
        pool.submit(task3);

        pool.shutdown();
    }
}
